<template>
  <layout-content header="StatefulSets">
    <div style="float: left">
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'statefulsets',
          verb: 'create'
        }"
        type="primary"
        size="small"
        @click="onHandleCreate(true)"
      >
        YAML
      </el-button>
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'statefulsets',
          verb: 'create'
        }"
        type="primary"
        size="small"
        @click="onHandleCreate()"
      >
        {{ $t("commons.button.create") }}
      </el-button>
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'deployments',
          verb: 'update'
        }"
        type="primary"
        size="small"
        :disabled="selections.length === 0"
        @click="onHandleScale()"
      >
        {{ $t("commons.button.scale") }}
      </el-button>
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'statefulsets',
          verb: 'delete'
        }"
        type="primary"
        size="small"
        :disabled="selections.length === 0"
        @click="confirmDelete()"
      >
        {{ $t("commons.button.delete") }}
      </el-button>
    </div>
    <complex-table
      v-model:selects="selections"
      v-loading="uiState.loading"
      :data="srcList"
      :pagination-config="query.paginationConfig"
      :search-config="query.searchConfig"
      @search="reloadResourceList"
    >
      <el-table-column type="selection" fix />
      <el-table-column
        :label="$t('commons.table.name')"
        prop="name"
        min-width="120"
        show-overflow-tooltip
      >
        <template #default="{ row }">
          <el-button link type="primary" @click="onHandleViewDetails(row)">
            {{ row.metadata.name }}
          </el-button>
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('business.namespace.namespace')"
        min-width="80"
        prop="metadata.namespace"
      />
      <el-table-column :label="$t('commons.table.status')" min-width="40">
        <template #default="{ row }">
          {{ row.status.readyReplicas || 0 }} / {{ row.status.replicas }}
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('commons.table.created_time')"
        min-width="60"
        prop="metadata.creationTimestamp"
        fix
      >
        <template #default="{ row }">
          {{ getAge(row.metadata.creationTimestamp) }}
        </template>
      </el-table-column>
      <ko-table-operations
        :buttons="options.buttons"
        :label="$t('commons.table.action')"
      />
    </complex-table>

    <el-dialog
      v-model="options.dialogScaleVisible"
      :title="$t('commons.button.scale')"
      width="50%"
      :close-on-click-modal="false"
    >
      <el-form
        ref="form"
        label-position="top"
        style="margin-left: 30px"
        :model="scaleEditForm"
      >
        <div>
          <el-form-item
            :label="
              $t('business.common.basic') + '  (namespace / name / replicas)'
            "
          >
            <el-table :data="scaleEditForm.targets">
              <el-table-column label="Namespace" prop="metadata.namespace" />
              <el-table-column label="Name" prop="metadata.name" />
              <el-table-column label="Replicas" prop="spec.replicas">
                <template #default="{ row }">
                  <ko-data-item
                    v-model:model-value="row.spec.replicas"
                    :min="0"
                    item-type="number"
                  />
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
        </div>
      </el-form>
      <template v-slot:footer>
        <div class="dialog-footer">
          <el-button size="small" @click="options.dialogScaleVisible = false">
            {{ $t("commons.button.cancel") }}
          </el-button>
          <el-button size="small" @click="onHandleScaleSubmit">
            {{ $t("commons.button.confirm") }}
          </el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog
      v-model="options.dialogModifyVersionVisible"
      :title="$t('commons.button.modifying_version')"
      width="70%"
      :close-on-click-modal="false"
    >
      <complex-table
        v-loading="options.imageVersionFormLoading"
        :data="containerImages"
      >
        <el-table-column
          :label="$t('business.workload.container_type')"
          prop="type"
          min-width="10"
        />
        <el-table-column
          :label="$t('business.workload.name')"
          prop="name"
          min-width="20"
          show-overflow-tooltip
        />
        <el-table-column
          :label="$t('business.workload.container_image')"
          prop="image"
          min-width="40"
          show-overflow-tooltip
        />
        <el-table-column
          :label="$t('business.workload.current_version')"
          prop="version"
          min-width="15"
        />
        <el-table-column
          :label="$t('business.workload.new_version')"
          prop="newVersion"
          min-width="20"
        >
          <template #default="{ row }">
            <ko-data-item v-model="row.newVersion" itemType="input" />
          </template>
        </el-table-column>
      </complex-table>
      <template v-slot:footer>
        <div class="dialog-footer">
          <el-button
            size="small"
            @click="options.dialogModifyVersionVisible = false"
          >
            {{ $t("commons.button.cancel") }}
          </el-button>
          <el-button size="small" @click="onModifyVersionSubmit">
            {{ $t("commons.button.confirm") }}
          </el-button>
        </div>
      </template>
    </el-dialog>
  </layout-content>
</template>

<script setup lang="ts">
import LayoutContent from "@/views/domain/kubeHud/views/components/layout/LayoutContent.vue";
import KoDataItem from "@/views/domain/kubeHud/views/components/ko-data-item/index.vue";
import KoTableOperations from "@/views/domain/kubeHud/views/components/ko-table-operations/index.vue";
import ComplexTable from "@/views/domain/kubeHud/views/components/complex-table/index.vue";
import { useI18n } from "vue-i18n";
import {
  RestartSourceOperation,
  StatefulSet,
  useK8SApi
} from "@/views/domain/kubeHud/api/k8s";
import {
  useBaseCRUDProvider,
  useBaseCRUDRoute
} from "@/views/domain/kubeHud/api/provider/baseListProvider";
import { reactive, ref } from "vue";
import { KRouteStatefulSet } from "@/views/domain/kubeHud/router";
import { checkPermissions } from "@/views/domain/kubeHud/utils/permission";
import { WorkloadEditContainerType } from "../provider";
import { getAge } from "@/views/domain/kubeHud/utils";
import { SafePromiseAll } from "@/utils/promise";
import { ElMessage } from "element-plus";

// import {
//   listWorkLoads,
//   deleteWorkLoad,
//   getWorkLoadByName
// } from "@/api/workloads";
// import { scaleStatefulset, patchStatefulset } from "@/api/statefulsets";
// import { downloadYaml } from "@/utils/actions";
// import { checkPermissions } from "@/utils/permission";

type Prop = {};
const props = defineProps<Prop>();

const { t } = useI18n();
const { statefulSetRepo } = useK8SApi();

const {
  selections,
  srcList,
  query,
  router,
  uiState,
  downloadSourceAsYaml,
  getResourceDetails,
  getResourceList,
  updateResource,
  deleteResource,
  confirmDelete,
  reloadResourceList
} = useBaseCRUDProvider({
  request: {
    getDetailsReq: statefulSetRepo.getStatefulSetDetail,
    getListReq: statefulSetRepo.getStatefulSet,
    updateReq: statefulSetRepo.updateStatefulSet,
    deleteReq: statefulSetRepo.deleteStatefulSet,
    createReq: statefulSetRepo.createStatefulSet
  }
});

const { pushTo } = useBaseCRUDRoute({ router });
const options = reactive({
  dialogScaleVisible: false,
  dialogModifyVersionVisible: false,
  editStatefulSet: undefined as StatefulSet | undefined,
  imageVersionFormLoading: false,
  scaleFromLoading: false,
  buttons: [
    {
      label: t("commons.button.edit"),
      icon: "el-icon-edit",
      click: row => {
        pushTo(KRouteStatefulSet.Edit, {
          operation: "edit",
          namespace: row.metadata.namespace,
          name: row.metadata.name
        });
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "statefulsets",
          verb: "update"
        });
      }
    },
    {
      label: t("commons.button.scale"),
      icon: "el-icon-copy-document",
      click: row => {
        onHandleScale(row);
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "statefulsets",
          verb: "update"
        });
      }
    },
    {
      label: t("commons.button.modifying_version"),
      icon: "el-icon-edit-outline",
      click: row => {
        onModifyVersion(row);
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "statefulsets",
          verb: "update"
        });
      }
    },
    {
      label: t("commons.button.restart"),
      icon: "el-icon-refresh",
      click: row => {
        onRestartStatefulSet(row);
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "statefulsets",
          verb: "update"
        });
      }
    },
    {
      label: t("commons.button.edit_yaml"),
      icon: "el-icon-edit",
      click: row => {
        pushTo(KRouteStatefulSet.Edit, {
          operation: "edit",
          namespace: row.metadata.namespace,
          name: row.metadata.name,
          yaml: "true"
        });
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "statefulsets",
          verb: "update"
        });
      }
    },
    {
      label: t("commons.button.download_yaml"),
      icon: "el-icon-download",
      click: row => {
        downloadSourceAsYaml(row);
      }
    },
    {
      label: t("commons.button.delete"),
      icon: "el-icon-delete",
      click: row => {
        confirmDelete(row);
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "statefulsets",
          verb: "delete"
        });
      }
    }
  ]
});

const scaleEditForm = ref<{ replicas: number; targets: StatefulSet[] }>();

type EditImageType = {
  type: WorkloadEditContainerType;
  name: string;
  image: string;
  version?: string;
  newVersion?: string;
};

const containerImages = ref<EditImageType[]>([]);

const onHandleCreate = (yaml?: boolean) => {
  pushTo(KRouteStatefulSet.Create, { yaml: yaml ? "true" : "" });
};

const onHandleViewDetails = (row: StatefulSet) => {
  pushTo(KRouteStatefulSet.Details, {
    name: row.metadata.name,
    namespace: row.metadata.namespace
  });
};

const parseImage = (
  image: string
): { image: string; version?: string; newVersion?: string } => {
  const lastSplit = image.lastIndexOf(":");
  if (lastSplit === -1) {
    return { image };
  }
  return {
    image: image.substring(0, lastSplit),
    version: image.substring(lastSplit + 1),
    newVersion: image.substring(lastSplit + 1)
  };
};

const onModifyVersion = (row: StatefulSet) => {
  containerImages.value = [];
  options.editStatefulSet = row;

  // 加载container
  containerImages.value.push(
    ...(row.spec.template?.spec?.containers?.map(c => ({
      type: WorkloadEditContainerType.Standard,
      name: c.name,
      ...parseImage(c.image)
    })) ?? [])
  );

  // 加载initContainer
  containerImages.value.push(
    ...(row.spec.template?.spec?.initContainers?.map(c => ({
      type: WorkloadEditContainerType.Init,
      name: c.name,
      ...parseImage(c.image)
    })) ?? [])
  );

  options.dialogModifyVersionVisible = true;
};

const onModifyVersionSubmit = () => {
  if (!options.editStatefulSet) return;
  uiState.loading = true;

  // 更新镜像
  options.editStatefulSet.spec?.template?.spec?.containers?.forEach(c => {
    const newImageOpt = containerImages.value.find(
      c => c.type === WorkloadEditContainerType.Standard && c.name === c.name
    );
    if (newImageOpt) {
      c.image = `${newImageOpt.image}:${newImageOpt.newVersion}`;
    }
  });

  // 更新initContainer
  options.editStatefulSet.spec?.template?.spec?.initContainers?.forEach(c => {
    const newImageOpt = containerImages.value.find(
      c => c.type === WorkloadEditContainerType.Init && c.name === c.name
    );
    if (newImageOpt) {
      c.image = `${newImageOpt.image}:${newImageOpt.newVersion}`;
    }
  });
  statefulSetRepo.patchStatefulSet({}, options.editStatefulSet).then(res => {
    if (res) {
      options.dialogModifyVersionVisible = false;
      uiState.loading = false;
      options.editStatefulSet = undefined;
      containerImages.value = [];
    }
  });
};

const onRestartStatefulSet = (row: StatefulSet) => {
  statefulSetRepo
    .patchStatefulSet(row, RestartSourceOperation as any)
    .then(res => {});
};

const onHandleScale = (row?: StatefulSet) => {
  scaleEditForm.value = {
    replicas: row?.spec?.replicas ?? 1,
    targets: row ? [...new Set([row, ...selections.value])] : selections.value
  };
  options.dialogScaleVisible = true;
};
const onHandleScaleSubmit = () => {
  options.scaleFromLoading = true;
  SafePromiseAll(
    scaleEditForm.value.targets.map(sf =>
      statefulSetRepo.patchStatefulSet({}, sf)
    )
  ).then(res => {
    if (res.some(r => r.err)) {
      ElMessage.error(t("commons.status.Failed"));
    } else {
      ElMessage.success(t("commons.status.Succeeded"));

      options.dialogScaleVisible = false;
      options.scaleFromLoading = false;
      scaleEditForm.value = undefined;
    }
  });
};
</script>
